/// Creator:      gaoruishan
/// CreatDate:    2025-07-01
/// Description:  血糖相关
Class Nur.MNISV3.Service.Sugar Extends %RegisteredObject [ Not ProcedureBlock ]
{

/// 查询血糖数据（录入）
/// w ##class(Nur.MNISV3.Service.Sugar).GetSugarPatListV4("","2025-07-03","","3","20665","8","2","{""single"":"""",""multiple"":""1""}")
ClassMethod GetSugarPatListV4(episodeId, date, time, wardId, userId, locId, hospitalId, extras) As %String
{
    n (episodeId, date, time, wardId, userId, locId, hospitalId, extras,%session)
    s $zt="errGetSugarPatListV4"
    s ^GRS("GetSugarPatListV4")=$lb(episodeId, date, time, wardId, userId, locId, hospitalId, extras)
    s Msg="成功",msgcode="999999",Status="0" //定义初始值
    s json=##class(%ArrayOfDataTypes).%New()
    s fromDate=##class(Nur.Tools).Date(date)
    s toDate=##class(Nur.Tools).Date(date)
    s obgGradeItems=..GetObgGradeItems(hospitalId)
    s obsItems=..GetObgItems(hospitalId)
    s obsPats=##class(%ListOfDataTypes).%New()
    i episodeId'="" {//单患者
        s patinfo=##class(%ArrayOfDataTypes).%New()
        //基本患者信息
        s patinfo=##class(Nur.MNISV3.Service.Patient).GetBasicInfo(patinfo,episodeId)
        s obsData=..GetObgDataObjByDateRange(episodeId,fromDate,toDate,obsItems)
        d patinfo.SetAt($g(obsData),"obgData")
        d obsPats.Insert(patinfo)
    }else {
        //调用纯净版患者列表，
        s patListObj=##class(%ResultSet).%New("Nur.MNISV3.Service.Patient:GetPatList")
        d patListObj.Execute(wardId,userId,"Ward",locId)
        while(patListObj.Next()){
            s patinfo=##class(Nur.MNISV3.Common.Utils).ResultSet(patListObj)
            s episodeId=patListObj.GetDataByName("episodeId")
            s obsData=..GetObgDataObjByDateRange(episodeId,fromDate,toDate,obsItems)
            //s obsData=##class(Nur.MNISV3.Service.Temperature).GetObsDataObjByDateRange(episodeId,fromDate,toDate,obsItems)
            d patinfo.SetAt($g(obsData),"obgData")
            //基本患者信息
            s patinfo=##class(Nur.MNISV3.Service.Patient).GetBasicInfo(patinfo,episodeId)
            d obsPats.Insert(patinfo)
        }
    }
    d json.SetAt($g(Msg),"msg")
    d json.SetAt($g(msgcode),"msgcode")
    d json.SetAt($g(Status),"status")
    d json.SetAt($g(obsPats),"patients") 
    d json.SetAt($g(obsItems),"obgItems") 
    d json.SetAt($g(obgGradeItems),"obgGradeItems")
    q ##class(Nur.MNISV3.Common.JSON).Encode(json)
errGetSugarPatListV4
    s Msg=$ze
    q ##class(Nur.MNISV3.Common.Utils).ReturnMsgJson(Msg,"100021","-1")
}

/// 保存血糖数据
/// w ##class(Nur.MNISV3.Service.Sugar).SaveSugarDataV4(
ClassMethod SaveSugarDataV4(wardId, userId, locId, hospitalId, patients)
{
    n (wardId, userId, locId, hospitalId,patients)
    s $zt="errSaveSugarDataV4"
    s ^GRS("SaveSugarDataV4")=$lb(wardId, userId, locId, hospitalId,patients)
    s Msg="成功",msgcode="999999",Status="0" //定义初始值
    s json=##class(%ArrayOfDataTypes).%New()
    s obgGradeItems=..GetObgGradeItems(hospitalId)
    s obsItems=..GetObgItems(hospitalId)
    ;;;保存了复测值不再允许修改原始值
    s allowToEditOriginalValueEvenWhenRetested=1
    d ..ParseObsInput(.temp,patients,"obgData","retests")
    s admInd="" f  s admInd=$o(temp(admInd)) q:(admInd="")  d
    .s episodeId=$g(temp(admInd))
    .s obsInd="" f  s obsInd=$o(temp(admInd,obsInd)) q:(obsInd="")||($g(error)'="")  d
    ..s obgObj=$g(temp(admInd,obsInd)),value=$lg(obgObj,4),delete=0
    ..s retestInd=$o(temp(admInd,obsInd,""))
    ..i (retestInd="")||(allowToEditOriginalValueEvenWhenRetested) d
    ...s ret=..SaveObgValue(episodeId,obgObj,"",obgGradeItems,userId,wardId,hospitalId)
    ...s sc=..ParseResult(ret,.error,.message,.toast)
    ...s value=$lg(obgObj,4)
    ...i (sc=0)&&(value="") s delete=1
    ..s retestInd="" f  s retestInd=$o(temp(admInd,obsInd,retestInd)) q:(retestInd="")||($g(error)'="")  d
    ...s retestObj=$g(temp(admInd,obsInd,retestInd))
    ...i (delete) s $li(retestObj,4)=""
    ...s ret=..SaveObgValue(episodeId,retestObj,"Y",obgGradeItems,userId,wardId,hospitalId)
    ...s sc=..ParseResult(ret,.error,.message,.toast)
    i $g(error)'="" s Status="-1",Msg=error //错误提示
    d json.SetAt($g(msgcode),"msgcode")
    d json.SetAt($g(Status),"status")
    d json.SetAt($g(toast),"toast")
    d json.SetAt($g(Msg),"msg")
    q ##class(Nur.MNISV3.Common.JSON).Encode(json)
errSaveSugarDataV4
    s Msg=$ze
    q ##class(Nur.MNISV3.Common.Utils).ReturnMsgJson(Msg,"100021","-1")
}

/// 获取详情
/// w ##class(Nur.MNISV3.Service.Sugar).GetPatSugarDetailV4()
ClassMethod GetPatSugarDetailV4(episodeId, fromDate, toDate, wardId, userId, locId, hospitalId, extras) As %String
{
    n (episodeId,fromDate, toDate, wardId, userId, locId, hospitalId, extras,%session)
    s $zt="errGetPatSugarDetailV4"
    s ^GRS("GetPatSugarDetailV4")=$lb(episodeId,fromDate, toDate, wardId, userId, locId, hospitalId, extras) 
    s Msg="成功",msgcode="999999",Status="0" //定义初始值
    s json=##class(%ArrayOfDataTypes).%New()
    s fromDate=##class(Nur.Tools).Date(fromDate)
    s toDate=##class(Nur.Tools).Date(toDate)
    s obgGradeItems=..GetObgGradeItems(hospitalId)
    s obsItems=..GetObgItems(hospitalId)
    s obsPats=##class(%ListOfDataTypes).%New()
    s patinfo=##class(%ArrayOfDataTypes).%New()
    //基本患者信息
    s patinfo=##class(Nur.MNISV3.Service.Patient).GetBasicInfo(patinfo,episodeId)
    s obsData=..GetObgDataObjByDateRange(episodeId,fromDate,toDate,obsItems)
    d patinfo.SetAt($g(obsData),"obgData")
    d obsPats.Insert(patinfo)
    d json.SetAt($g(Msg),"msg")
    d json.SetAt($g(msgcode),"msgcode")
    d json.SetAt($g(Status),"status")
    d json.SetAt($g(obsPats),"patients") 
    d json.SetAt($g(obsItems),"obgItems") 
    d json.SetAt($g(obgGradeItems),"obgGradeItems")
    q ##class(Nur.MNISV3.Common.JSON).Encode(json)
errGetPatSugarDetailV4
    s Msg=$ze
    q ##class(Nur.MNISV3.Common.Utils).ReturnMsgJson(Msg,"100021","-1")
}

/// 删除血糖数据
/// w ##class(Nur.MNISV3.Service.Sugar).DeleteSugarDataV4()
ClassMethod DeleteSugarDataV4(wardId, userId, locId, hospitalId, patients)
{
    n (wardId, userId, locId, hospitalId,patients)
    s $zt="errDeleteSugarDataV4"
    s ^GRS("DeleteSugarDataV4")=$lb(wardId, userId, locId, hospitalId,patients)
    s Msg="成功",msgcode="999999",Status="0" //定义初始值
    s json=##class(%ArrayOfDataTypes).%New()
    d ..ParseObsInput(.temp,patients,"obgData","retests")
    s admInd="" f  s admInd=$o(temp(admInd)) q:(admInd="")  d
    .s obsInd="" f  s obsInd=$o(temp(admInd,obsInd)) q:(obsInd="")  d
    ..s obgObj=$g(temp(admInd,obsInd))
    ..s id=$lg(obgObj,7)
    ..i ($g(idStr)'="") s idStr=$g(idStr)_","
    ..s idStr=$g(idStr)_id
    ..s retestInd="" f  s retestInd=$o(temp(admInd,obsInd,retestInd)) q:(retestInd="")  d
    ...s retestObj=$g(temp(admInd,obsInd,retestInd))
    ...s retestId=$lg(retestObj,7)
    ...i ($g(idStr)'="") s idStr=$g(idStr)_","
    ...s idStr=$g(idStr)_retestId
    s ret=##class(Nur.NIS.Service.VitalSign.BloodGlucoseV2).delVitalSign("["_$g(idStr)_"]")
    d json.SetAt($g(Msg),"msg")
    d json.SetAt($g(ret),"msgcode")
    d json.SetAt($g(Status),"status")
    q ##class(Nur.MNISV3.Common.JSON).Encode(json)
errDeleteSugarDataV4
    s Msg=$ze
    q ##class(Nur.MNISV3.Common.Utils).ReturnMsgJson(Msg,"100021","-1")
}

ClassMethod ParseResult(ret, ByRef error, ByRef message, ByRef toast) As %String
{
    n (ret,error,message,toast)
    s ec=$p(ret,"^"),ms=$p(ret,"^",2)
    i (ec=-1) s ec="请录入血糖值"
    i (ms="") s ms=ec
    s mt=$match(ec,"\d+\|\|\d+")
    s sc=(ec'=0)&&('mt)
    i (sc) {
        i ($g(error)="") s error=ms
    } elseif ('mt) {
        i ($g(message)="") s message=ms
    }
    q sc
}

ClassMethod SaveObgValue(episodeId, obgObj, retest, obgGradeItems, userId, wardId, hospId) As %String
{
    n (episodeId,obgObj,retest,obgGradeItems,userId,wardId,hospId,%session)
    s date=$lg(obgObj,1)
    s time=$lg(obgObj,2)
    s code=$lg(obgObj,3)
    s value=$lg(obgObj,4)
    s notes=$lg(obgObj,5)
    s measure=$lg(obgObj,6)
    s id=$lg(obgObj,7)
    s obsItemId=..getObsIDByCode(code)
    s nurMeasureRequire=..GetGradeProperty(obgGradeItems,value,"nurMeasureRequire")
    s retestFlag=..GetGradeProperty(obgGradeItems,value,"retestFlag")
    s data="{""nurMeasureRequire"":"""_nurMeasureRequire_
        """,""retestFlag"":"""_retestFlag_
        """,""itemDr"":"""_obsItemId_
        """,""value"":"""_value_
        """,""episodeID"":"""_episodeId_
        """,""verify"":"""_retest_
        """,""date"":"""_date_
        """,""rowId"":"""_id_
        """,""time"":"""_time_
        """,""measure"":"""_measure_
        """,""note"":"""_notes_
        """}"
    s ret=##class(Nur.NIS.Service.VitalSign.BloodGlucoseV2).saveSingleVitalSign( data,userId,wardId,hospId)
    q ret
}

ClassMethod GetObgGradeItems(hospId) As %String
{
    n (hospId,%session)
    s resSet=##class(%ResultSet).%New("Nur.NIS.Service.VitalSign.BloodGlucoseCfg:GetBGWarn")
    d resSet.Execute(hospId)
    s obgGradeItems=##class(Nur.Tools).ResultSetToList(resSet)
    s len=obgGradeItems.Count()
    f ind=1:1:len {
        s item=obgGradeItems.GetAt(ind)
        s nurseMeasureDetail=item.GetAt("nurseMeasureDetail")
        s ^GRS("nurseMeasureDetail")=nurseMeasureDetail
        s nurseMeasureDetailAsList=##class(Nur.Tools).GetOptionsAsList(nurseMeasureDetail,$c(13))
        d item.SetAt(nurseMeasureDetailAsList,"nurseMeasureDetail")
    }
    q obgGradeItems
}

ClassMethod GetObgItems(hospId) As %String
{
    n (hospId,%session)
    s resSet=##class(%ResultSet).%New("Nur.NIS.Service.VitalSign.BloodGlucoseCfg:GetBGConfig")
    d resSet.Execute(hospId,"Y")
    s items=##class(Nur.Tools).ResultSetToList(resSet)
    s list=##class(%ListOfDataTypes).%New()
    s len=items.Count()
    f ind=1:1:len {
        s item=items.GetAt(ind)
        s obj=##class(Nur.Tools).RapidMapping(
            "VSId,VSCode,VSDesc,errorLow,errorHigh",item,
            "rowid","code","desc","errorValueLowTo","errorValueHightFrom" )
        s specialChar=item.GetAt("specialChar")
        s symbol=##class(Nur.Tools).GetOptionsAsList(specialChar,$c(129))
        d obj.SetAt(symbol,"symbol")
        d obj.SetAt(item.GetAt("startTime"),"startTime")
        d obj.SetAt(item.GetAt("endTime"),"endTime")
        d list.Insert(obj)
    }
    q list
}

ClassMethod GetObgDataObjByDateRange(episodeId, fromDate, toDate, obgItems) As %String
{
    n (episodeId,fromDate,toDate,obgItems,%session)
    s stdate=##class(Nur.Tools).Date(fromDate)
    s eddate=##class(Nur.Tools).Date(toDate)
    s obgDataObj=##class(%ListOfDataTypes).%New()
    s mradmId=$p($g(^PAADM(episodeId)),"^",61)
    q:(mradmId="") obgDataObj
    d ##class(Nur.Tools).InnerMappingTemp(.obgItemTemp,obgItems,"rowid","code")
    k obgDataArr,obgDataDateCountArr,obgRetestArr,obgDateRetestIndArr
    s dateFor=stdate-1 f  s dateFor=$o(^MR(mradmId,"OBS",0,"Date",dateFor)) q:(dateFor="")||(dateFor>eddate)  d
    .s obsIdFor="" f  s obsIdFor=$o(^MR(mradmId,"OBS",0,"Date",dateFor,obsIdFor)) q:(obsIdFor="")  d
    ..q:('$d(obgItemTemp(obsIdFor)))
    ..s obsChl="" f  s obsChl=$o(^MR(mradmId,"OBS",0,"Date",dateFor,obsIdFor,obsChl)) q:(obsChl="")  d
    ...s timeFor=$p($g(^MR(mradmId,"OBS",obsChl)),"^",4)
    ...s retestFor=$p($g(^MR(mradmId,"OBS",obsChl)),"^",7)
    ...i (retestFor="Y") s obgRetestArr(dateFor,timeFor,obsChl)=obsIdFor
    ...e  s obgDataArr(dateFor,timeFor,obsChl)=obsIdFor
    ;;;记录当天同一项目的第几次复测
    s dateFor="" f  s dateFor=$o(obgRetestArr(dateFor)) q:(dateFor="")  d
    .s timeFor="" f  s timeFor=$o(obgRetestArr(dateFor,timeFor)) q:(timeFor="")  d
    ..s obsChl="" f  s obsChl=$o(obgRetestArr(dateFor,timeFor,obsChl)) q:(obsChl="")  d
    ...s obsIdFor=$g(obgRetestArr(dateFor,timeFor,obsChl))
    ...s obgDateRetestInd=$o(obgDateRetestIndArr(dateFor,obsIdFor,""),-1)+1
    ...s obgDateRetestIndArr(dateFor,obsIdFor,obgDateRetestInd)=obsChl
    ;;;同一时间点可能录入两种以上的血糖值
    s dateFor="" f  s dateFor=$o(obgDataArr(dateFor)) q:(dateFor="")  d
    .s timeFor="" f  s timeFor=$o(obgDataArr(dateFor,timeFor)) q:(timeFor="")  d
    ..d ..AddTimeObj(dateFor,timeFor,.timeObj,.dataObj,.obgDataObj)
    ..s obsChl="" f  s obsChl=$o(obgDataArr(dateFor,timeFor,obsChl)) q:(obsChl="")  d
    ...s obgObj=..GetObgObjById(mradmId_"||"_obsChl)
    ...d dataObj.Insert(obgObj)
    ...s retests=##class(%ListOfDataTypes).%New()
    ...d obgObj.SetAt(retests,"retests")
    ...s obsIdFor=$g(obgDataArr(dateFor,timeFor,obsChl))
    ...s obgDataDateCount=$i(obgDataDateCountArr(dateFor,obsIdFor))
    ...s obsRetestChl=$g(obgDateRetestIndArr(dateFor,obsIdFor,obgDataDateCount))
    ...q:(obsRetestChl="")
    ...d ..AddTimeObj(dateFor,timeFor,.retestTimeObj,.retestDataObj,.retests)
    ...s obgRetestObj=..GetObgObjById(mradmId_"||"_obsRetestChl)
    ...d retestDataObj.Insert(obgRetestObj)
    q obgDataObj
}

ClassMethod AddTimeObj(date, time, ByRef timeObj, ByRef dataObj, ByRef obgDataObj) As %String
{
    n (date,time,timeObj,dataObj,obgDataObj)
    s timeObj=##class(%ArrayOfDataTypes).%New()
    d timeObj.SetAt(##class(Nur.Tools).ToDate(date,3),"date")
    d timeObj.SetAt(##class(Nur.Tools).ToTime(time,2),"time")
    s dataObj=##class(%ListOfDataTypes).%New()
    d timeObj.SetAt(dataObj,"data")
    d obgDataObj.Insert(timeObj)
    q $$$OK
}

ClassMethod GetObgObjById(id) As %String
{
    n (id,%session)
    s mradmId=+id,obsChl=$p(id,"||",2)
    s obsData=$g(^MR(mradmId,"OBS",obsChl))
    s obsId=$p(obsData,"^",1)
    s value=$p(obsData,"^",2)
    s userId=$p(obsData,"^",5)
    s retest=$p(obsData,"^",7)
    s notes=$p(obsData,"^",16)
    s recDate=$p(obsData,"^",19)
    s recTime=$p(obsData,"^",20)
    s measure=$p(obsData,"^",21)
    s obsCode=..GetObsItemCode(obsId)
    s obsDesc=..GetObsItemDesc(obsId)
    s recDate=##class(Nur.Tools).ToDate(recDate,3)
    s recTime=##class(Nur.Tools).ToTime(recTime,2)
    s recUser=##class(Nur.Tools).ToUser(userId,2)
    s obj=##class(Nur.Tools).RapidAssembly(
        "code,value,notes,retest,recDate,recTime,recUser,measure,ID,desc,obsId",
        obsCode,value,notes,retest,recDate,recTime,recUser,measure,id,obsDesc,obsId)
    q obj
}

/**
 * 病人列表带数据的模式十分规则，但是层次结构太深，需要单独解析
 * 体征类输入解析：适用于体征和血糖
 */
ClassMethod ParseObsInput(ByRef temp, patients, nodeName, childNodeName) As %String
{
    n (temp,patients,nodeName,childNodeName,%session)
    k temp,admIndArr
    s patientData=##class(Nur.MNISV3.Common.JSON).Decode(patients)
    s patientDataLen=patientData.Count()
    f patientDataInd=1:1:patientDataLen {
        s patient=patientData.GetAt(patientDataInd)
        s episodeId=patient.GetAt("episodeID")
        continue:(episodeId="")
        s obsData=patient.GetAt(nodeName)
        i '$isobject(obsData) s obsData=##class(Nur.MNISV3.Common.JSON).Decode(obsData)
        s obsDataLen=obsData.Count()
        f obsDataInd=1:1:obsDataLen {
            s timeObj=obsData.GetAt(obsDataInd)
            s date=timeObj.GetAt("date")
            s time=timeObj.GetAt("time")
            s data=timeObj.GetAt("data")
            s len=data.Count()
            f ind=1:1:len {
                i ('$d(admIndArr(episodeId))) {
                    s admInd=$o(temp(""),-1)+1
                    s admIndArr(episodeId)=admInd
                    s temp(admInd)=episodeId
                } else {
                    s admId=$g(admIndArr(episodeId))
                }
                s obsInd=$o(temp(admInd,""),-1)+1
                s obsObj=data.GetAt(ind)
                s temp(admInd,obsInd)=..ParseObsObj(obsObj,date,time)
                s retests=obsObj.GetAt(childNodeName)
                i retests'=""  d ..ParseRetestInput(.temp,admInd,obsInd,retests)
            }
        }
    }
    q $$$OK
}

ClassMethod ParseRetestInput(ByRef temp, admInd, obsInd, retests) As %String [ Internal ]
{
    n (temp,admInd,obsInd,retests)
    s obsData=##class(Nur.MNISV3.Common.JSON).Decode(retests)
    s obsDataLen=obsData.Count()
    f obsDataInd=1:1:obsDataLen {
        s timeObj=obsData.GetAt(obsDataInd)
        s date=timeObj.GetAt("date")
        s time=timeObj.GetAt("time")
        s data=timeObj.GetAt("data")
        s len=data.Count()
        f ind=1:1:len {
            s retestInd=$o(temp(admInd,obsInd,""),-1)+1
            s temp(admInd,obsInd,retestInd)=..ParseObsObj(data.GetAt(ind),date,time)
        }
    }
    q $$$OK
}

ClassMethod ParseObsObj(obsObj, date, time) As %String [ Internal ]
{
    q $lb(date,time,
        obsObj.GetAt("code"),obsObj.GetAt("value")
        ,obsObj.GetAt("notes"),obsObj.GetAt("measure"),
        obsObj.GetAt("ID")
        )
}

ClassMethod getObsIDByCode(code) [ Private ]
{
    s hospitalID=##class(Nur.NIS.Common.Utils).GetHospitalID(##class(Nur.NIS.Common.ConstVal).#TABLEOBS)
    s rtn=""
    s itemID="" f  s itemID=$o(^MRC("OBITM",0,"HOSPCode",hospitalID,$$$ALPHAUP(code),"")) q:(itemID="")!(rtn'="")  d
    #;.q:##class(Nur.NIS.Common.Utils).DataAccessFlag("MRC_ObservationItem",itemID)="N"
    .s rtn=itemID
    q rtn
}

ClassMethod GetGradeProperty(obgGradeItems, value, name) As %String
{
    n (obgGradeItems,value,name)
    i (value'="") {
        s obgGradeLen=obgGradeItems.Count()
        f obgGradeInd=1:1:obgGradeLen {
            s obgGradeItem=obgGradeItems.GetAt(obgGradeInd)
            s condition=obgGradeItem.GetAt("condition")
            s result=0
            i (condition["||") {
                s expr1=$p(condition,"||",1)
                s expr2=$p(condition,"||",2)
                s result=##class(Nur.Tools).EvalExpr(expr1,value)||##class(Nur.Tools).EvalExpr(expr2,value)
            } elseif (condition["&&") {
                s expr1=$p(condition,"&&",1)
                s expr2=$p(condition,"&&",2)
                s result=##class(Nur.Tools).EvalExpr(expr1,value)&&##class(Nur.Tools).EvalExpr(expr2,value)
            } elseif (condition'="") {
                s result=##class(Nur.Tools).EvalExpr(condition,value)
            }
            i (result) {
                return:$s($g(name)'="":obgGradeItem.GetAt(name),1:obgGradeItem)
            }
        }
    }
    q ""
}

ClassMethod GetObsItemCode(id) As %String
{
    n (id)
    q $s(id'="":$p($g(^MRC("OBITM",id)),"^",1),1:"")
}

ClassMethod GetObsItemDesc(id) As %String
{
    n (id)
    q $s(id'="":$p($g(^MRC("OBITM",id)),"^",2),1:"")
}

}
